package com.allin.mall.common.redis.configurer;

import com.allin.mall.common.redis.serializer.GsonRedisSerializer;
import com.allin.mall.common.redis.service.RedisDistributedLock;
import com.allin.mall.common.redis.service.RedisService;
import com.allin.mall.common.redis.service.impl.RedisDistributedLockImpl;
import com.allin.mall.common.redis.service.impl.RedisServiceImpl;
import com.google.gson.Gson;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.util.StreamUtils;

import java.nio.charset.StandardCharsets;

@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class RedisConfigurer {


    @Bean
    public RedisScript<Long> lockScript() {
        return loadScript("lock.lua");
    }

    @Bean
    public RedisScript<Long> unlockScript() {
        return loadScript("unlock.lua");
    }

    @Bean
    public RedisSerializer<Object> serializer(Gson gson) {
        return new GsonRedisSerializer<>(StandardCharsets.UTF_8, gson, Object.class);
    }

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory, RedisSerializer<Object> serializer) {

        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory);

        // Key 序列化
        StringRedisSerializer stringSerializer = StringRedisSerializer.UTF_8;
        template.setKeySerializer(stringSerializer);
        template.setHashKeySerializer(stringSerializer);

        // Value 序列化
        template.setValueSerializer(serializer);
        template.setHashValueSerializer(serializer);

        return template;
    }

    @Bean
    public RedisService redisService() {
        return new RedisServiceImpl();
    }

    @Bean
    public RedisDistributedLock redisDistributedLock() {
        return new RedisDistributedLockImpl();
    }

    /**
     * 从资源文件加载Lua脚本
     */
    private RedisScript<Long> loadScript(String scriptName) {
        ClassPathResource resource = new ClassPathResource("lua/" + scriptName);
        try {
            String scriptContent = StreamUtils.copyToString(resource.getInputStream(), StandardCharsets.UTF_8);
            return new DefaultRedisScript<>(scriptContent, Long.class);
        } catch (Exception e) {
            return null;
        }
    }
}
